<style lang="less" scoped>
    .pull-to-refresh-layer{
        width: 100%;
        height: 60px;
        text-align: center;
        font-size: 16px;
        color: #aaa;
        position: absolute;
        left: 0;
        top: 0;
        .spinner-holder{
            text-align: center;
            -webkit-font-smoothing: antialiased;
        }
        .arrow{
            width: 20px;
            height: 20px;
            margin: 8px auto 0;
            -webkit-transform: translateZ(0) rotate(0deg);
            transform: translateZ(0) rotate(0deg);
            transition: transform .2s linear;
        }
        .text{
            display: block;
            margin: 0 auto;
            font-size: 14px;
            line-height: 20px;
            color: #aaa;
        }
        .spinner{
            margin-top: 14px;
            width: 32px;
            height: 32px;
            fill: rgb(170, 170, 170);
            stroke: rgb(170, 170, 170);
        }
        &.active{
            .arrow{
                transform: translateZ(0) rotate(180deg);
            }
        }
    }
</style>
<style>
    .list-wrapper .weui-loadmore_line{
        margin: 1.5em auto !important;
        width: 100%;
    }
</style>
<template>
    <div ref="wrapper" class="list-wrapper">
        <div class="scroll-content">
            <div ref="listWrapper">
                <slot>
                    <!-- TODO 去除子元素  元素自定义-->
                    <!--<ul class="list-content">
                        <li @click="clickItem($event,item)" class="list-item" v-for="item in data">{{item}}</li>
                    </ul>-->
                </slot>
                <slot name="pullup"
                      :pullUpLoad="pullUpLoad"
                      :isPullUpLoad="isPullUpLoad"
                >
                    <div class="pullup-wrapper" v-if="pullUpLoad">
                        <div class="before-trigger" v-if="!isPullUpLoad">
                            <load-more :show-loading="false" tip="我是有底线的" background-color="#fbf9fe"></load-more>
                        </div>
                        <div class="after-trigger" v-else>
                            <loading></loading>
                        </div>
                    </div>
                </slot>
            </div>
        </div>
        <slot name="pulldown"
              :pullDownRefresh="pullDownRefresh"
              :pullDownStyle="pullDownStyle"
              :beforePullDown="beforePullDown"
              :isPullingDown="isPullingDown"
              :bubbleY="bubbleY"
        >
            <div ref="pulldown" class="pulldown-wrapper" :style="pullDownStyle" v-if="pullDownRefresh">
                <div class="before-trigger pull-to-refresh-layer" :style="{top:bubbleY + 'px'}" :class="bubbleY  > 0 ? 'active':''" v-if="beforePullDown">
                    <!--<bubble :y="bubbleY"></bubble>-->   <!-- todo canvas动画-->
                    <div class="spinner-holder">
                    <svg data-v-ecaca2b0="" viewBox="0 0 63.657 63.657" xml:space="preserve" width="512px" height="512px" class="arrow"><g><g><g><g><polygon points="31.891,63.657 0.012,35.835 2.642,32.821 31.886,58.343 61.009,32.824 63.645,35.832" fill="#AAA"></polygon></g></g> <g><g><rect x="29.827" width="4" height="60" fill="#AAA"></rect></g></g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g> <g></g></svg>
                    <span data-v-ecaca2b0="" class="text" style="color: rgb(170, 170, 170);">下拉刷新</span>
                    </div>
                </div>
                <div class="after-trigger" v-else>
                    <div v-if="isPullingDown" class="loading">
                        <loading></loading>
                    </div>
                    <div v-else><span style="color: rgb(170, 170, 170);">{{refreshTxt}}</span></div>
                </div>
            </div>
        </slot>
    </div>
</template>

<script type="text/ecmascript-6">
  import {mapState} from 'vuex'
  import Loading from './loading/loading.vue'
  import Bubble from './bubble.vue'
  import {getRect} from "../js/common";
  import {LoadMore} from 'vux'
  const COMPONENT_NAME = 'scroll'
  const DIRECTION_H = 'horizontal'
  const DIRECTION_V = 'vertical'
  export default {
    name: COMPONENT_NAME,
    props: {
      probeType: {
        type: Number,
        default: 1
      },
      click: {
        type: Boolean,
        default: true
      },
      listenScroll: {
        type: Boolean,
        default: false
      },
      listenBeforeScroll: {
        type: Boolean,
        default: false
      },
      listenScrollEnd: {
        type: Boolean,
        default: false
      },
      direction: {
        type: String,
        default: DIRECTION_V
      },
      scrollbar: {
        type: null,
        default: false
      },
      pullDownRefresh: {
        type: null,
        default: false
      },
      pullUpLoad: {
        type: null,
        default: false
      },
      startY: {
        type: Number,
        default: 0
      },
      refreshDelay: {
        type: Number,
        default: 20
      },
      freeScroll: {
        type: Boolean,
        default: false
      },
      mouseWheel: {
        type: Boolean,
        default: false
      },
      bounce: {
        default: true
      },
      zoom: {
        default: false
      }
    },
    data() {
      return {
        beforePullDown: true,
        isRebounding: false,
        isPullingDown: false,
        isPullUpLoad: false,
        pullUpDirty: true,
        pullDownStyle: '',
        bubbleY: 0
      }
    },
    computed: {
      ...mapState({
        interactive: state => state.interactive,
      }),
      pullUpTxt() {
        const moreTxt = (this.pullUpLoad && this.pullUpLoad.txt && this.pullUpLoad.txt.more) || 'scrollComponent.defaultLoadTxtMore'
        const noMoreTxt = (this.pullUpLoad && this.pullUpLoad.txt && this.pullUpLoad.txt.noMore) || 'scrollComponent.defaultLoadTxtNoMore'
        return this.pullUpDirty ? moreTxt : noMoreTxt
      },
      refreshTxt() {
        return (this.pullDownRefresh && this.pullDownRefresh.txt) || '刷新成功'
      }
    },
    created() {
      this.pullDownInitTop = -60
    },
    mounted() {
      setTimeout(() => {
        this.$nextTick(()=>{
          this.initScroll()
        })
      }, 20)
    },
    destroyed() {
      this.$refs.scroll && this.$refs.scroll.destroy()
    },
    methods: {
      initScroll() {
        if (!this.$refs.wrapper) {
          return
        }
        if (this.$refs.listWrapper && (this.pullDownRefresh || this.pullUpLoad)) {
          this.$refs.listWrapper.style.minHeight = `${getRect(this.$refs.wrapper).height + 1}px`
          this.$refs.listWrapper.style.paddingBottom = document.querySelector('.tabBar')? (getRect(this.$refs.wrapper).width / 750 * 100) + (parseFloat(this.interactive.statusBarHeight.tabBarHeight) * 100 * getRect(this.$refs.wrapper).width / 750) + 'px' : (parseFloat(this.interactive.statusBarHeight.tabBarHeight) * 100 * getRect(this.$refs.wrapper).width / 750) + 'px'
        }
        let options = {
          probeType: this.probeType,
          click: this.click,
          scrollY: this.freeScroll || this.direction === DIRECTION_V,
          scrollX: this.freeScroll || this.direction === DIRECTION_H,
          scrollbar: this.scrollbar,
          pullDownRefresh: this.pullDownRefresh,
          pullUpLoad: this.pullUpLoad,
          startY: this.startY,
          freeScroll: this.freeScroll,
          mouseWheel: this.mouseWheel,
          bounce: this.bounce,
          zoom: this.zoom,
          stopPropagation:true
        }
        this.scroll = new BScroll(this.$refs.wrapper, options)
        if (this.listenScroll) {
          this.scroll.on('scroll', (pos) => {
            this.$emit('pageScrol', pos)
          })
        }
        if (this.listenScrollEnd) {
          this.scroll.on('scrollEnd', (pos) => {
            this.$emit('scroll-end', pos)
          })
        }
        if (this.listenBeforeScroll) {
          this.scroll.on('beforeScrollStart', () => {
            this.$emit('beforeScrollStart')
          })
          this.scroll.on('scrollStart', () => {
            this.$emit('scroll-start')
          })
        }
        if (this.pullDownRefresh) {
          this._initPullDownRefresh()
        }
        if (this.pullUpLoad) {
          this._initPullUpLoad()
        }
      },
      disable() {
        this.scroll && this.scroll.disable()
      },
      enable() {
        this.scroll && this.scroll.enable()
      },
      refresh() {
        this.scroll && this.scroll.refresh()
      },
      scrollTo() {
        this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
      },
      scrollToElement() {
        this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
      },
      destroy() {
        this.scroll.destroy()
      },
      forceUpdate(dirty) {
        if (this.pullDownRefresh && this.isPullingDown) {
          this.isPullingDown = false
          this._reboundPullDown().then(() => {
            this._afterPullDown()
          })
        } else if (this.pullUpLoad && this.isPullUpLoad) {
          this.isPullUpLoad = false
          this.scroll.finishPullUp()
          this.pullUpDirty = dirty
          this.refresh()
        } else {
          this.refresh()
        }
      },
      _initPullDownRefresh() {
        this.scroll.on('pullingDown', () => {
          this.beforePullDown = false
          this.isPullingDown = true
          this.$emit('pullingDown')
        })
        this.scroll.on('scroll', (pos) => {
          if (!this.pullDownRefresh) {
            return
          }
          if (this.beforePullDown) {
            this.bubbleY = Math.max(0, pos.y + this.pullDownInitTop)
            this.pullDownStyle = `top:${Math.min(pos.y + this.pullDownInitTop, 0)}px`
          } else {
            this.bubbleY = 0
          }
          if (this.isRebounding) {
            this.pullDownStyle = `top:${10 - (this.pullDownRefresh.stop - pos.y)}px`
          }
        })
      },
      _initPullUpLoad() {
        this.scroll.on('pullingUp', () => {
          this.isPullUpLoad = true
          this.$emit('pullingUp')
        })
      },
      _reboundPullDown() {
        const {stopTime = 600} = this.pullDownRefresh
        return new Promise((resolve) => {
          setTimeout(() => {
            this.isRebounding = true
            this.scroll.finishPullDown()
            resolve()
          }, stopTime)
        })
      },
      _afterPullDown() {
        setTimeout(() => {
          this.pullDownStyle = `top:${this.pullDownInitTop}px`
          this.beforePullDown = true
          this.isRebounding = false
          this.refresh()
        }, this.scroll.options.bounceTime)
      }
    },
    watch: {
      data() {
        setTimeout(() => {
          this.forceUpdate(true)
        }, this.refreshDelay)
      }
    },
    components: {
      Loading,
      Bubble,
      LoadMore
    }
  }
</script>

<style lang="less">
    .list-wrapper {
        position: relative;
        height: 100%;
        /*position: absolute*/
        /*left: 0*/
        /*top: 0*/
        /*right: 0*/
        /*bottom: 0*/
        overflow: hidden;
    }

    .scroll-content {
        position: relative;
        z-index: 1
    }

    .list-content {
        position: relative;
        z-index: 10;
        background: #fff;
    }

    .list-item {
        height: 60px;
        line-height: 60px;
        font-size: 18px;
        padding-left: 20px;
        border-bottom: 1px solid #e5e5e5;
    }

    .pulldown-wrapper {
        position: absolute;
        width: 100%;
        left: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        transition: all;
    }

    .after-trigger {
        margin-top: 10px

    }

    .pullup-wrapper {
        width: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 16px 0;
    }

</style>